<template>
  <div class="morph">
    <div class="canvas" ref="canvas"></div>
  </div>
</template>

<script lang="ts">
import { Vue, Options } from 'vue-property-decorator';
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
// import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js';
import logo from '../assets/logo.png';
const logoSrc = import.meta.globEager('../assets/*.png');
const scene =  new THREE.Scene();
const camera = new THREE.PerspectiveCamera(80, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 40);
const point  = new THREE.PointLight(0xffffff);
point.position.set(400, 200, 300);
scene.add(point);
const ambient = new THREE.AmbientLight(0x444444);
scene.add(ambient);
const renderer = new THREE.WebGLRenderer({
  alpha: true,
  antialias: true,
});
renderer.debug.checkShaderErrors = false;
renderer.setClearColor(new THREE.Color(), 0);
renderer.setPixelRatio(750 / window.innerWidth);
let mesh!: THREE.Mesh;
@Options({ components: {} })
export default class MorphTargets extends Vue {
  public rect: DOMRect|null = null;

  public onWindowResize() {
    camera.updateProjectionMatrix();
    scene.add(camera);
    renderer.setSize(window.innerWidth, window.innerHeight);
  }
  public initGUI() {
    // const params = {
    //   Spherify: 0,
    //   Twist: 0,
    // };
    // const gui = new GUI({ title: 'Morph Targets' });
    // gui.add(params, 'Spherify', 0, 1).step(0.01)
    //   .onChange((value: any) => {
    //     mesh.morphTargetInfluences[0] = value;
    //   });
    // gui.add(params, 'Twist', 0, 1).step(0.01)
    //   .onChange((value: any) => {
    //     mesh.morphTargetInfluences[1] = value;
    //   });
  }
  public createGeometry() {
    const geometry = new THREE.BoxGeometry(2, 2, 2, 32, 32, 32);
    // morphAttributes存储 BufferAttribute 的 Hashmap，存储了几何体 morph targets 的细节信息。
    geometry.morphAttributes.position = [];
    const positionAttribute = geometry.attributes.position;
    const spherePositions = [];
    const twistPositions: any[] = [];
    const direction = new THREE.Vector3(1, 0, 0);
    const vertex = new THREE.Vector3();

    for (let i = 0;i < positionAttribute.count;i++) {
      const x = positionAttribute.getX(i);
      const y = positionAttribute.getY(i);
      const z = positionAttribute.getZ(i);
      spherePositions.push(
        x * Math.sqrt(1 - (y * y / 2) - (z * z / 2) + (y * y * z * z / 3)),
        y * Math.sqrt(1 - (z * z / 2) - (x * x / 2) + (z * z * x * x / 3)),
        z * Math.sqrt(1 - (x * x / 2) - (y * y / 2) + (x * x * y * y / 3)),
      );
      vertex.set(x * 2, y, z);
      vertex.applyAxisAngle(direction, Math.PI * x / 2).toArray(twistPositions, twistPositions.length);
    }
    geometry.morphAttributes.position[0] = new THREE.Float32BufferAttribute(spherePositions, 3);
    geometry.morphAttributes.position[1] = new THREE.Float32BufferAttribute(twistPositions, 3);
    return geometry;
  }
  public mounted() {
    this.rect = (this.$el as HTMLElement).getBoundingClientRect();
    renderer.setSize(this.rect.width, this.rect.height, false);
    (this.$refs.canvas as HTMLDivElement).append(renderer.domElement);

    const geometry = this.createGeometry();
    const material = new THREE.MeshPhongMaterial({
      color: 0xff0000,
      flatShading: true,
    });
    mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh);

    // this.initGUI();

    renderer.setAnimationLoop(() => {
      renderer.render(scene, camera);
    });

    const controls = new OrbitControls(camera, renderer.domElement);
    controls.enableZoom = false;

    window.addEventListener('resize', this.onWindowResize);
  }
}
</script>

<style lang="postcss" scoped>
  .morph{
    touch-action: none;
    position: absolute;
    left: 0;top: 0;
    width: 100%;height: 100%;
    background: #98bbd1;
 .canvas{
      position: absolute;
      left: 0;top: 0;
      width: 100%;height: 100%;
       :deep(canvas){
        width: 100%;height: 100%;
      }
    }
  }
</style>
